package com.example.rabbitmq.starter.config;

import com.example.rabbitmq.starter.entity.MQConfigInfo;
import com.example.rabbitmq.starter.service.MQConfigService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.core.*;
import org.springframework.amqp.rabbit.core.RabbitAdmin;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;
import lombok.RequiredArgsConstructor;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 动态RabbitMQ配置，负责根据数据库配置动态创建交换机和队列
 */
@Component
@RequiredArgsConstructor
public class DynamicRabbitMQConfig implements CommandLineRunner {

    private static final Logger log = LoggerFactory.getLogger(DynamicRabbitMQConfig.class);

    private final RabbitAdmin rabbitAdmin;

    private final MQConfigService mqConfigService;

    /**
     * 初始化时从数据库加载MQ配置并创建交换机和队列
     */
    @Override
    public void run(String... args) {
        try {
            createMQFromDatabase();
        }
        catch (Exception e) {
            log.error("初始化RabbitMQ配置失败", e);
        }
    }

    /**
     * 从数据库加载配置并创建交换机和队列
     */
    public void createMQFromDatabase() {
        log.info("开始从数据库加载RabbitMQ配置");
        List<MQConfigInfo> configList = mqConfigService.getAllConfigs();
        log.info("共加载到{}个RabbitMQ配置", configList.size());

        for (MQConfigInfo config : configList) {
            // 现在所有队列（包括死信队列）都通过数据库配置创建
            if (config.isEnabled()) {
                try {
                    createExchangeAndQueue(config);
                    log.info("成功创建交换机和队列: {}", config.getBusinessName());
                }
                catch (Exception e) {
                    log.error("创建交换机和队列失败: {}, 错误: {}", config.getBusinessName(), e.getMessage(), e);
                    // 尝试更安全的创建方式
                    try {
                        createExchangeAndQueueSafely(config);
                    }
                    catch (Exception ex) {
                        log.error("安全创建交换机和队列也失败: {}, 错误: {}", config.getBusinessName(), ex.getMessage(), ex);
                    }
                }
            }
        }
    }

    /**
     * 创建单个交换机和队列
     *
     * @param config MQ配置信息
     */
    public void createExchangeAndQueue(MQConfigInfo config) {
        // 创建交换机
        Exchange exchange = createExchange(config);
        rabbitAdmin.declareExchange(exchange);

        // 创建队列
        Queue queue = createQueue(config);
        rabbitAdmin.declareQueue(queue);

        // 创建绑定关系
        Binding binding = createBinding(queue, exchange, config.getRoutingKey());
        rabbitAdmin.declareBinding(binding);
    }

    /**
     * 安全地创建交换机和队列（处理已存在的情况）
     *
     * @param config MQ配置信息
     */
    public void createExchangeAndQueueSafely(MQConfigInfo config) {
        log.info("尝试安全创建交换机和队列: {}", config.getBusinessName());

        try {
            // 先尝试删除现有队列
            try {
                rabbitAdmin.deleteQueue(config.getQueueName());
                log.info("删除现有队列成功: {}", config.getQueueName());
            }
            catch (Exception e) {
                log.warn("删除队列失败或队列不存在: {}, {}", config.getQueueName(), e.getMessage());
            }

            // 创建交换机
            Exchange exchange = createExchange(config);
            rabbitAdmin.declareExchange(exchange);
            log.info("创建交换机成功: {}", config.getExchangeName());

            // 创建队列，但不设置任何参数
            Queue queue = new Queue(config.getQueueName(),
                    config.isQueueDurable(),
                    false,
                    config.isQueueAutoDelete());
            rabbitAdmin.declareQueue(queue);
            log.info("创建简单队列成功: {}", config.getQueueName());

            // 创建绑定关系
            Binding binding = createBinding(queue, exchange, config.getRoutingKey());
            rabbitAdmin.declareBinding(binding);
            log.info("创建绑定关系成功: {} -> {}", config.getExchangeName(), config.getQueueName());
        }
        catch (Exception e) {
            log.error("安全创建失败: {}", e.getMessage(), e);
            throw e;
        }
    }

    /**
     * 根据配置创建交换机
     *
     * @param config MQ配置信息
     * @return 交换机对象
     */
    private Exchange createExchange(MQConfigInfo config) {
        String exchangeType = config.getExchangeType();
        boolean durable = config.isExchangeDurable();

        if ("topic".equalsIgnoreCase(exchangeType)) {
            return ExchangeBuilder.topicExchange(config.getExchangeName())
                    .durable(durable)
                    .build();
        }
        else if ("fanout".equalsIgnoreCase(exchangeType)) {
            return ExchangeBuilder.fanoutExchange(config.getExchangeName())
                    .durable(durable)
                    .build();
        }
        else if ("headers".equalsIgnoreCase(exchangeType)) {
            return ExchangeBuilder.headersExchange(config.getExchangeName())
                    .durable(durable)
                    .build();
        }
        else {
            // 默认为direct类型
            return ExchangeBuilder.directExchange(config.getExchangeName())
                    .durable(durable)
                    .build();
        }
    }

    /**
     * 根据配置创建队列
     *
     * @param config MQ配置信息
     * @return 队列对象
     */
    private Queue createQueue(MQConfigInfo config) {
        Map<String, Object> args = new HashMap<>();

        // 如果有队列参数，复制它们
        if (config.getQueueArguments() != null && !config.getQueueArguments().isEmpty()) {
            args.putAll(config.getQueueArguments());
        }



        // 构建队列
        QueueBuilder queueBuilder = QueueBuilder.durable(config.getQueueName());

        if (!args.isEmpty()) {
            queueBuilder.withArguments(args);
        }

        if (config.isQueueAutoDelete()) {
            queueBuilder.autoDelete();
        }

        return queueBuilder.build();
    }

    /**
     * 创建绑定关系
     *
     * @param queue      队列对象
     * @param exchange   交换机对象
     * @param routingKey 路由键
     * @return 绑定对象
     */
    private Binding createBinding(Queue queue, Exchange exchange, String routingKey) {
        if (exchange instanceof TopicExchange) {
            return BindingBuilder.bind(queue)
                    .to((TopicExchange) exchange)
                    .with(routingKey);
        }
        else if (exchange instanceof FanoutExchange) {
            return BindingBuilder.bind(queue)
                    .to((FanoutExchange) exchange);
        }
        else if (exchange instanceof HeadersExchange) {
            return BindingBuilder.bind(queue)
                    .to((HeadersExchange) exchange)
                    .where("key").matches(routingKey);
        }
        else {
            return BindingBuilder.bind(queue)
                    .to((DirectExchange) exchange)
                    .with(routingKey);
        }
    }

    /**
     * 删除交换机和队列
     *
     * @param config MQ配置信息
     */
    public void deleteExchangeAndQueue(MQConfigInfo config) {
        try {
            // 删除绑定关系（先解绑）
            rabbitAdmin.removeBinding(
                    BindingBuilder.bind(new Queue(config.getQueueName()))
                            .to(new DirectExchange(config.getExchangeName()))
                            .with(config.getRoutingKey())
            );

            // 删除队列
            rabbitAdmin.deleteQueue(config.getQueueName());

            // 删除交换机
            rabbitAdmin.deleteExchange(config.getExchangeName());

            log.info("成功删除交换机和队列: {}", config.getBusinessName());
        }
        catch (Exception e) {
            log.error("删除交换机和队列失败: {}, 错误: {}", config.getBusinessName(), e.getMessage(), e);
            throw e;
        }
    }
}